#pragma once

#include "const.h"
#include "message.grpc.pb.h"
#include "Singleton.h"
#include "ConfigManager.h"

#include <grpc++/grpc++.h>

class GRPCConPool : public Singleton<GRPCConPool>
{
	friend class Singleton<GRPCConPool>;

public:
	GRPCConPool(size_t pool_size, std::string host, std::string port);
	~GRPCConPool();

	GRPCConPool(const GRPCConPool&) = delete;
	GRPCConPool& operator=(const GRPCConPool&) = delete;

	std::unique_ptr<message::VerifyService::Stub> getConnection();

	void returnConnection(std::unique_ptr<message::VerifyService::Stub> stub);

	void Close();

private:
	std::queue<std::unique_ptr<message::VerifyService::Stub>> m_connections;
	size_t m_pool_size;
	std::string m_host;
	std::string m_port;
	std::mutex m_mutex;
	std::condition_variable m_cond;
	std::atomic_bool m_b_stop;
};

class VerifyGrpcClient : public Singleton<VerifyGrpcClient>
{
	friend class Singleton<VerifyGrpcClient>;

public:
	~VerifyGrpcClient() = default;

	message::GetVerifyRsp GetVerifyCode(std::string email) {
		grpc::ClientContext context;
		message::GetVerifyRsp reply;
		message::GetVerifyReq request;
		request.set_email(email);

		// 从GRPCConPool取出一个连接
		auto stub = m_pool->getConnection();
		grpc::Status status = stub->GetVerifyCode(&context, request, &reply);
		if (status.ok()) {
			m_pool->returnConnection(std::move(stub));
			return reply;
		}
		else {
			m_pool->returnConnection(std::move(stub));
			reply.set_error(ErrorCodes::RPCFailed);
			return reply;
		}
	}

private:
	VerifyGrpcClient() {
		auto& gCfgMgr = ConfigManager::getInstance();
		std::string host = gCfgMgr["VerifyServer"]["Host"];
		std::string port = gCfgMgr["VerifyServer"]["Port"];
		m_pool.reset(new GRPCConPool(5, host, port));
	}

private:
	std::unique_ptr<GRPCConPool> m_pool; 
};

